
#include "samplers.fx"
#include "shading.fx"

struct VS_IN
{
	float3 position : POSITION;
	float3 normal	: NORMAL;
	float3 tangent : TANGENT;
	float2 tex		: TEX_COORDS;
};

struct VS_OUT
{
	float4 position : SV_POSITION;
	float4 ws_pos	: WS_POSITION;
	float3 normal	: NORMAL;
	float2 tex		: TEX_COORDS;
};

struct Material
{
	float4	ambient;
	float4	diffuse;
	float4	specular;
	float4	vIsTextured;	// x:diffuse, y:specular, z:normal
};
Texture2D	tex_diffuse;
Texture2D	tex_specular;
Texture2D	tex_normal;

Texture2D	texTerrainHeight;

float4x4	m_World;
float4x4	m_WorldViewProj;


float3 alienVertexTransform(float3 position)
{	
	float3 modified_Lpos = position;

	// ____VS-based alien transform

	// __a: big head! translate the back part of the head so the alien 
	// appears to have an enormous head
	if (position.z < 0.10f && position.y > 2.3f) {
		modified_Lpos.yz += float2(0.15f,-0.45f);
		modified_Lpos *= float3(1.2,1.1,1.2); // should merge!
	}

	// __b: arms! alien will have very long arms
	else if (position.x > 1.8f) // R
		modified_Lpos.x += 1.5f;
	else if (position.x < -1.8f) // L
		modified_Lpos.x -= 1.5f;
	
	// __c: legs! merge the two legs
	else if (position.y < -0.4f) {
		// amount of translation depends on the y value
		float t = smoothstep(-3.9f, 0.4f, position.y);
		t = (1.0f - t) * 0.40f;
		modified_Lpos.x  -= sign(position.x) * t;

		// legs lower part (shoes)
		if (position.y < -3.2f)
			modified_Lpos *= float3(0.5f, 1.0f, 0.3f);
	}

	// __d: tail! translate the vertices at the back of the model
	else if (position.z < 0.0f && abs(position.x) < 0.2f &&
								  abs(position.y+0.3f) < 0.2f)
		modified_Lpos += float3(0, 1.5f, -1.5f);

	return modified_Lpos;
}



float getTerrainHeight(float3 wpos)
{
	float GRID_WIDTH = 200.0f;

	float u = wpos.x / GRID_WIDTH + 0.5f;
	float v = wpos.y / GRID_WIDTH + 0.5f;

	return texTerrainHeight.SampleLevel(s_linear, float2(u,v), 0).x;

}



VS_OUT VS_Alien(VS_IN vin)
{
	VS_OUT vout;

	float3 modifiedPos = alienVertexTransform(vin.position);

	float3 wpos = float3(m_World._41, m_World._42, m_World._43);
	modifiedPos.y  += getTerrainHeight(wpos) * 10.0f - 10.0f;

	vout.position = mul(float4(modifiedPos, 1.0f), m_WorldViewProj);
	vout.ws_pos = mul(float4(modifiedPos, 1.0f), m_World);
	vout.normal = mul(float4(vin.normal, 0.0f), m_World).xyz;
	vout.tex =	  vin.tex;

	return vout;
}


float4 PS_Alien(VS_OUT pin) : SV_TARGET
{
	float3 diffuse = tex_diffuse.Sample(s_linear, pin.tex).xyz;

	diffuse *= shade(pin.normal);

	return float4(diffuse,1);
}



RasterizerState rs_Wireframe
{
	CullMode = Back;
	FillMode = Wireframe;
};


technique10 AlienVS
{
	pass P0
	{
		SetVertexShader( CompileShader( vs_4_0,  VS_Alien()   ) );
		SetHullShader ( NULL );
		SetDomainShader( NULL );
		SetGeometryShader( NULL);
		SetPixelShader( CompileShader( ps_4_0,   PS_Alien()   ) );
	}
}
